package com.cn.pool1;

import java.io.IOException;
import java.nio.channels.Selector;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;

/*
 * 抽象selector线程类 
 */
public abstract class AbstractNioSelector implements Runnable {

	//线程池
	private final Executor executor;
	//选择器
	protected Selector selector;
	//选择器wakenUp状态标记
	protected final AtomicBoolean wakenUp = new AtomicBoolean();
	//任务队列
	private final Queue<Runnable> taskQueue = new ConcurrentLinkedDeque<Runnable>();
	//线程名称
	private String threadName;
	//线程管理对象
	protected NioSelectorRunnablePool selectorRunnablePool;

	public AbstractNioSelector(Executor executor, 
			String threadName, NioSelectorRunnablePool selectorRunnablePool) {
		this.executor = executor;
		this.threadName = threadName;
		this.selectorRunnablePool = selectorRunnablePool;
		//启动一个线程
		openSelector();
	}
	
	// select抽象方法
	protected abstract int select(Selector selector) throws IOException;

	// selector的业务处理
	protected abstract void process(Selector selector) throws IOException;

	

	@Override
	public void run() {
		// TODO Auto-generated method stub
		Thread.currentThread().setName(this.threadName);

		while (true) {

			try {
				wakenUp.set(false);

				select(selector);//多久刷新阻塞一次

				processTaskQueue();//执行线程里的任务
				
				process(selector);//执行处理业务
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}
	
	
	//注册一个任务并激活
	protected final void registerTask(Runnable task){
		taskQueue.add(task);
		
		Selector selector = this.selector;
		if (selector!=null) {
			if (wakenUp.compareAndSet(false, true)) {
				selector.wakeup();
			}
		}else{
			taskQueue.remove(task);
		}
	}
	
	//执行队列里的任务
	private void processTaskQueue(){
		for (;;) {
			//获取任务，并且清除队列取出来的任务
			final Runnable task = taskQueue.poll();
			if (task==null) {
				break;
			}
			task.run();
		}
	}

	// 获取线程管理对象
	public NioSelectorRunnablePool getSelectorRunnablePool() {
		return selectorRunnablePool;
	}

	/*
	 * 获取并且启动线程
	 */
	private void openSelector() {
		try {
			this.selector = Selector.open();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException("Failed to create a selector.");
		}
		executor.execute(this);
	}

}
